// HSS.Forms.DetailModuleContainer.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       DetailModuleContainer.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/23/2010
// ----------------------------------------------------------------------------
namespace HSS.Forms
{
	#region Using Directives
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Drawing;
	using System.Windows.Forms;
	using HSS.Data;

	#endregion

	#region DetailModuleContainer
	/// <summary>
	/// DetailModuleContainer is a generic Form that can host UserControls that implement DetailModuleBase.
	/// </summary>
	public partial class DetailModuleContainer : System.Windows.Forms.Form
	{
		#region Fields
		static object lockObject = new object();
		private bool _onNewOverride;
		private bool _isDialog;
		private const string _cmdNewText = "&New";
		private const string _cmdNewPLUSSaveText = "Save && &New";
		private const string _cmdApplyText = "&Apply";
		private const string _cmdSaveText = "&OK";
		private const string _cmdCancelText = "&Cancel";
		private const string _cmdCloseText = "&Close";
		#endregion

		#region Constructor
		/// <summary>
		/// Default Constructor
		/// </summary>
		public DetailModuleContainer()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}
		#endregion

		#region Child Module Handlers

		/// <summary>
		/// The dynamically added Module
		/// </summary>
		public HSS.Forms.DetailModuleBase ChildModule
		{
			get { return _childModule; }
			set { _childModule = value; }
		} HSS.Forms.DetailModuleBase _childModule;

		/// <summary>
		/// InitializeModule
		/// </summary>
		/// <param name="Action">ModuleActions</param>
		/// <param name="Data">The data to be edited</param>
		/// <param name="IsDialog">Should this Form be shown as a Modal Dialog.</param>
		/// <param name="HeaderText">The text to display in the header</param>
		public bool InitializeModule(ModuleActions Action, HSS.Data.IDataContainer Data, bool IsDialog, string HeaderText)
		{

			_childModule.UniqueID = "-1";

			// Remember if Dialog
			_isDialog = IsDialog;

			// Form Text (Window Header Bar)
			this.Text = HeaderText;

			// Init the Child Module Instance
			if (!_childModule.InitializeModule(Action, Data))
				return false;

			// Child Module's Parent Form Icon
			if (null != _childModule.ParentIcon)
				this.Icon = _childModule.ParentIcon;

			// Child Module - Image
			if (null != _childModule.Image)
				this.pbxModuleIcon.Image = _childModule.Image;

			// Optional New Button
			InitButton_New();

			// Optional Apply Button
			InitButton_Apply();

			// Optional OK/Save Button
			InitButton_Save();

			// Close/Cancel Button
			InitButton_Cancel();

			// ShowInTaskbar
			this.ShowInTaskbar = _childModule.ShowInTaskbar;

			// Maximize
			this.MaximizeBox = _childModule.MaximizeBox;

			// Minimize
			this.MinimizeBox = _childModule.MinimizeBox;

			// FormBorderStyle
			this.FormBorderStyle = _childModule.ParentBorderStyle;

			// Header Visible
			if (_childModule.HeaderVisible)
			{
				this.pnlHeader.Height = _childModule.HeaderHeight;

				// Module Title
				if (!string.IsNullOrEmpty(_childModule.ModuleTitle))
					this.ModuleTitle = _childModule.ModuleTitle;
				if (string.IsNullOrEmpty(this.ModuleTitle))
					this.ModuleTitle = "Module Editor";

				// Action Description
				if (!string.IsNullOrEmpty(_childModule.ActionDescription))
					this.ActionDescription = _childModule.ActionDescription;
				if (string.IsNullOrEmpty(this.ActionDescription))
					this.ActionDescription = "Set the configuration information for the selected Module.";
			}
			else
			{
				this.pnlHeader.Height = 0;
			}

			return true;
		}

		/// <summary>
		/// Initializes the NewButton state
		/// </summary>
		private void InitButton_New()
		{
			// New Button
			this.cmdNew.Visible = this._childModule.AllowCreateNew;

			this.cmdNew.Enabled = (this._childModule.AllowCreateNew == (this._childModule.CurrentAction != ModuleActions.New));

			this.cmdNew.Text = ((this._childModule.IsDirty) == (this._childModule.CurrentAction != ModuleActions.New)) ?
				DetailModuleContainer._cmdNewPLUSSaveText :
				DetailModuleContainer._cmdNewText;
		}


		/// <summary>
		/// Initializes the ApplyButton state
		/// </summary>
		private void InitButton_Apply()
		{
			this.cmdApply.Visible = _childModule.ShowApplyButton;
			this.cmdApply.Enabled = (this._childModule.AllowEdit == this._childModule.ShowApplyButton == this._childModule.IsDirty);
			this.cmdApply.Text = DetailModuleContainer._cmdApplyText;
		}


		/// <summary>
		/// Initializes the SaveButton state
		/// </summary>
		private void InitButton_Save()
		{
			this.cmdSave.Visible = _childModule.AllowEdit;
			this.cmdSave.Enabled = (this._childModule.AllowEdit == this._childModule.IsDirty);
			if (!string.IsNullOrEmpty(_childModule.OKButtonText))
				this.cmdSave.Text = _childModule.OKButtonText;
			else
				this.cmdSave.Text = DetailModuleContainer._cmdSaveText;
		}


		/// <summary>
		/// Initializes the CancelButton state
		/// </summary>
		private void InitButton_Cancel()
		{
			this.cmdCancel.Visible = true;
			this.cmdCancel.Enabled = true;
			this.cmdCancel.Text = (this._childModule.IsDirty ?
				DetailModuleContainer._cmdCancelText :
				DetailModuleContainer._cmdCloseText);
		}


		/// <summary>
		/// Updates the View of the Child Module to a dirty state
		/// </summary>
		/// <param name="e">DirtyEventArgs containing the State of the Child Module</param>
		/// <remarks>
		/// This is equivilant to modifying data in the Module
		/// </remarks>
		public void UpdateButtons_Dirty(DirtyEventArgs e)
		{

			// Save & New
			this.cmdNew.Visible = this._childModule.AllowCreateNew;
			this.cmdNew.Text = (e.IsDirty ? DetailModuleContainer._cmdNewPLUSSaveText : DetailModuleContainer._cmdNewText);
			if (e.IsDirty)
				this.cmdNew.Enabled = (e.IsEditing == this._childModule.AllowCreateNew);
			else
				this.cmdNew.Enabled = this._childModule.AllowCreateNew;

			// Apply
			this.cmdApply.Visible = this._childModule.ShowApplyButton;
			if (e.IsDirty)
				this.cmdApply.Enabled = (e.IsEditing == this._childModule.ShowApplyButton);
			else
				this.cmdApply.Enabled = false;

			// Save/OK
			this.cmdSave.Visible = this._childModule.AllowEdit;
			this.cmdSave.Enabled = (e.IsEditing == this._childModule.AllowEdit);

			// Close/Cancel
			this.cmdCancel.Text = (e.IsDirty ? DetailModuleContainer._cmdCancelText : DetailModuleContainer._cmdCloseText);

		}


		/// <summary>
		/// Updates the View of the Child Module to a new state
		/// </summary>
		/// <remarks>
		/// This is equivilant to Clicking the NewButton
		/// </remarks>
		public void ProcessCommand_New()
		{
			this.Cursor = Cursors.WaitCursor;
			try
			{
				ModuleActions current = this._childModule.CurrentAction;
				IDataContainer data = this._childModule.DetailData;
				if (_childModule.IsDirty)
				{
					if (SaveChildModuleData(true))
					{
						if (!this.InitializeModule(ModuleActions.New, null, this._isDialog, this.Text))
						{
							// UNDO
							this.InitializeModule(current, data, this._isDialog, this.Text);
						}
						else
						{
							_onNewOverride = true;
						}
					}
					else
					{
						_childModule.Focus();
					}
				}
				else
				{
					if (!this.InitializeModule(ModuleActions.New, null, this._isDialog, this.Text))
					{
						// UNDO
						this.InitializeModule(current, data, this._isDialog, this.Text);
					}
					else
					{
						_onNewOverride = true;
					}
				}
			}
			catch (Exception ex)
			{
				_childModule.MsgBox(ex.ToString());
			}
			finally
			{
				this.Cursor = Cursors.Default;
			}
		}


		/// <summary>
		/// Updates the View of the Child Module to a saved state
		/// </summary>
		/// <remarks>
		/// This is equivalent to Clicking the ApplyButton
		/// </remarks>
		public void ProcessCommand_Apply()
		{
			this.Cursor = Cursors.WaitCursor;
			try
			{
				if (SaveChildModuleData(false))
					this.InitializeModule(ModuleActions.Edit, this._childModule.DetailData, this._isDialog, this.Text);
				else
					_childModule.Focus();
			}
			catch (Exception ex)
			{
				_childModule.MsgBox(ex.ToString());
			}
			finally
			{
				this.Cursor = Cursors.Default;
			}
		}


		/// <summary>
		/// Updates the View of the Child Module to a saved state and possibly closing the Module
		/// if configured to do so
		/// </summary>
		/// <remarks>
		/// This is equivalent to Clicking the SaveButton
		/// </remarks>
		public void ProcessCommand_Save()
		{
			this.Cursor = Cursors.WaitCursor;
			try
			{
				if (SaveChildModuleData(false))
					this.Close();
				else
				{
					this.DialogResult = DialogResult.None;
					_childModule.Focus();
				}
			}
			catch (Exception ex)
			{
				_childModule.MsgBox(ex.ToString());
			}
			finally
			{
				this.Cursor = Cursors.Default;
			}
		}


		/// <summary>
		/// Updates the View of the Child Module to it's original state and possibly closing the Module
		/// if configured to do so
		/// </summary>
		/// <remarks>
		/// This is equivalent to Clicking the CancelButton
		/// </remarks>
		public void ProcessCommand_Cancel()
		{
			this.Cursor = Cursors.WaitCursor;
			try
			{
				switch (this.cmdCancel.Text)
				{
					case DetailModuleContainer._cmdCloseText: // CLOSE
						#region Close
						if (this.OkToClose())
							this.Close();
						#endregion
						break;

					case DetailModuleContainer._cmdCancelText: // CANCEL
						#region Cancel
						if (this._childModule.CloseOnCancel)
						{
							if (this.OkToClose())
								this.Close();
						}
						else
						{
							if (this._childModule.CurrentAction == ModuleActions.New |
								_onNewOverride)
							{
								this._childModule.WarnOnCancel = false;
								this.Close();
							}
							else
							{
								this.DialogResult = DialogResult.None;
								this.InitializeModule(this._childModule.CurrentAction, this._childModule.DetailData, this._isDialog, this.Text);
							}
						}
						#endregion
						break;
				}
			}
			catch { }
			finally
			{
				this.Cursor = Cursors.Default;
			}
			_onNewOverride = false;
		}


		/// <summary>
		/// Force a resize of the Parent Form (this)
		/// </summary>
		public void ResizeParent()
		{
			ResizeParent(_childModule.Size);
		}


		/// <summary>
		/// Force a resize of the Parent Form (this)
		/// </summary>
		/// <param name="NewSize">The minimum size for the Child Module</param>
		public void ResizeParent(Size NewSize)
		{
			if (this.WindowState == FormWindowState.Normal)
			{
				int newHeight =
					(this._childModule.HeaderVisible ? this._childModule.HeaderHeight : 0) +
					NewSize.Height +
					this.pnlFooter.Height;

				int newWidth = NewSize.Width;

				this.ClientSize = new Size(newWidth, newHeight);
			}
		}


		/// <summary>
		/// Indicates if this instance is the Active Instance
		/// </summary>
		public bool IsActive
		{
			get { return _isActive; }
			set { _isActive = value; }
		} bool _isActive = false;

		/// <summary>
		/// Ok To Close
		/// </summary>
		/// <returns>true if Data is not dirty; else false</returns>
		private bool OkToClose()
		{
			if (!this._childModule.IsDirty)
			{
				return true;
			}
			else
			{
				if (!this._childModule.WarnOnCancel)
				{
					return true;
				}
				else
				{
					DialogResult result = MessageBox.Show("Do you want to save changes?", Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
					switch (result)
					{
						case DialogResult.Yes:
							try
							{
								if (!SaveChildModuleData(false))
								{
									this.DialogResult = DialogResult.None;
									_childModule.Focus();
									return false;
								}
								else
								{
									return true;
								}
							}
							catch (Exception ex)
							{
								_childModule.MsgBox(ex.ToString());
							}
							break;
						case DialogResult.No:
							this._childModule.WarnOnCancel = false;
							return true;

						case DialogResult.Cancel:
							this.DialogResult = DialogResult.None;
							return false;

					}
				}
			}
			return true;
		}


		/// <summary>
		/// Save Child Module Data. Is a Wrapper for the _childModule.SaveData method
		/// </summary>
		/// <param name="SaveAndNew">Is this request to Save also request to create a new record</param>
		/// <returns>true if the Save was successful; else false</returns>
		private bool SaveChildModuleData(bool SaveAndNew)
		{
			bool success = _childModule.SaveData(SaveAndNew);
			if (success)
			{
				if (null != DetailModuleContainer.Saved && _childModule.RaiseSavedEvent)
					DetailModuleContainer.Saved(this, new DetailDataSavedEventArgs(_childModule.DetailData));
			}
			return success;
		}
		#endregion

		#region Properties
		/// <summary>
		/// The Title or Overview for the child Module
		/// </summary>
		[Description("The Title or Overview for the child Module")]
		[Category("Display")]
		public string ModuleTitle
		{
			get { return this.lblModuleTitle.Text; }
			set { this.lblModuleTitle.Text = value; }
		}
		/// <summary>
		/// The description or action for this child Module
		/// </summary>
		[Description("The description or action for this child Module")]
		[Category("Display")]
		public string ActionDescription
		{
			get { return this.lblActionDescription.Text; }
			set { this.lblActionDescription.Text = value; }
		}
		#endregion

		#region Events and Handlers
		private void _childModule_Dirty(object sender, DirtyEventArgs e)
		{
			UpdateButtons_Dirty(e);
		}

		private void cmdNew_Click(object sender, System.EventArgs e)
		{
			ProcessCommand_New();
		}

		private void cmdApply_Click(object sender, System.EventArgs e)
		{
			ProcessCommand_Apply();
		}
		private void cmdSave_Click(object sender, System.EventArgs e)
		{
			ProcessCommand_Save();
		}
		private void cmdCancel_Click(object sender, System.EventArgs e)
		{
			ProcessCommand_Cancel();
		}

		private void DetailModuleContainer_Activated(object sender, EventArgs e)
		{
			this.pnlFooter.Active = true;
			this._isActive = true;
		}
		private void DetailModuleContainer_Deactivate(object sender, EventArgs e)
		{
			this._isActive = false;
			this.pnlFooter.Active = false;
		}
		private void DetailModuleContainer_Closing(object sender, CancelEventArgs e)
		{
			e.Cancel = !this.OkToClose();
			if (!e.Cancel)
				CloseInstance(this);
		}

		private void _childModule_AllowCreateNewChanged(object sender, EventArgs e)
		{
			this.InitButton_New();
		}
		private void _childModule_AllowEditChanged(object sender, EventArgs e)
		{
			this.InitButton_Save();
		}
		private void _childModule_ShowApplyButtonChanged(object sender, EventArgs e)
		{
			this.InitButton_Apply();
		}
		#endregion

		#region Static Events
		/// <summary>
		/// Event to trigger when the Child Controlled has been saved
		/// </summary>
		public static event EventHandler<DetailDataSavedEventArgs> Saved;
		#endregion

		#region Static Properties
		/// <summary>
		/// The number of open Configuration Editor forms
		/// </summary>
		public static int InstanceCount
		{
			get { return _instanceCount; }
			set { _instanceCount = value; }
		} static int _instanceCount;
		/// <summary>
		/// Dictionary of Container Form Instances
		/// </summary>
		public static Dictionary<string, DetailModuleContainer> Instances()
		{
			return _instances;
		} static Dictionary<string, DetailModuleContainer> _instances = new Dictionary<string, DetailModuleContainer>();
		/// <summary>
		/// Returns the active instance
		/// </summary>
		public static DetailModuleContainer ActiveInstance
		{
			get
			{
				foreach (DetailModuleContainer instance in _instances.Values)
				{
					if (instance._isActive)
						return instance;
				}
				return null;
			}
		}
		#endregion

		#region Static Methods
		/// <summary>
		/// Returns the active instance specified by the ChildModule Name
		/// </summary>
		/// <param name="ChildModuleName">The name of the Child Module</param>
		public static DetailModuleContainer GetInstance(string ChildModuleName)
		{
			foreach (DetailModuleContainer instance in _instances.Values)
			{
				if (instance.ChildModule.Name == ChildModuleName)
					return instance;
			}
			return null;
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="ModuleTypeName">The TypeName of ChildModule to Load into the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		public static DialogResult LoadInstance(string ModuleTypeName, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog)
		{
			return LoadInstance(null, ModuleTypeName, FormTitle, Data, Action, ShowAsDialog, null);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="ModuleType">The Type of Module to Load into the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		public static DialogResult LoadInstance(Type ModuleType, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog)
		{
			return LoadInstance(null, ModuleType, FormTitle, Data, Action, ShowAsDialog, null);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="ModuleTypeName">The TypeName of ChildModule to Load into the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owning Parent of this Form</param>
		public static DialogResult LoadInstance(string ModuleTypeName, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog, IWin32Window owner)
		{
			return LoadInstance(null, ModuleTypeName, FormTitle, Data, Action, ShowAsDialog, owner);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="ModuleType">The Type of Module to Load into the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owning Parent of this Form</param>
		public static DialogResult LoadInstance(Type ModuleType, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog, IWin32Window owner)
		{
			return LoadInstance(null, ModuleType, FormTitle, Data, Action, ShowAsDialog, owner);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="DerivedContainer">The DerivedContainer</param>
		/// <param name="ModuleTypeName">The Type Name of ChildModule to Load into the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owing Parent Form</param>
		public static DialogResult LoadInstance(DetailModuleContainer DerivedContainer, string ModuleTypeName, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog, IWin32Window owner)
		{
			// The Type to create
			Type t = Type.GetType(ModuleTypeName, false);

			// Must have a valid Type to continue
			if (null == t)
				throw new InvalidCastException("Requested Module Type [ " + ModuleTypeName + " ] does not exist or is not available.");

			return LoadInstance(DerivedContainer, t, FormTitle, Data, Action, ShowAsDialog, owner);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="DerivedContainer">The DerivedContainer</param>
		/// <param name="ModuleType">The Type of Module to Load into the Container</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owing Parent Form</param>
		public static DialogResult LoadInstance(DetailModuleContainer DerivedContainer, Type ModuleType, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog, IWin32Window owner)
		{
			// Must have a valid Type to continue
			if (null == ModuleType)
				throw new ArgumentNullException("ModuleType", "You must specify the Module Type");

			HSS.Forms.DetailModuleBase _childModule = null;
			DialogResult result = DialogResult.None;
			DetailModuleContainer _detailForm = null;

			try
			{
				if (null != DerivedContainer)
				{
					_detailForm = DerivedContainer;
					_detailForm.Name += _detailForm.GetHashCode().ToString("x");
				}
				else
				{
					_detailForm = new DetailModuleContainer();
					_detailForm.Name = "DetailModuleContainer" + _detailForm.GetHashCode().ToString("x");
				}
				_detailForm.IsActive = true;
				_instances.Add(_detailForm.Name, _detailForm);
				System.Threading.Interlocked.Increment(ref _instanceCount);

				// Cast from DetailModuleBase to the Instance Type Requested.
				string moduleTypeName = ModuleType.FullName;
				_childModule = ModuleType.Assembly.CreateInstance(moduleTypeName) as HSS.Forms.DetailModuleBase;

				// Initialize the Container
				DetailModuleContainer.InitializeModuleContainer(_detailForm, _childModule, ModuleType.Name + InstanceCount.ToString());

				// Initialize the Module
				if (_detailForm.InitializeModule(Action, Data, ShowAsDialog, FormTitle))
				{
					if (ShowAsDialog)
					{
						result = _detailForm.ShowDialog(owner);
						if (null != _detailForm && !_detailForm.IsDisposed)
							_detailForm.Dispose(true);
					}
					else
					{
						_detailForm.Show(owner);
						_detailForm.BringToFront();
					}
				}
				else
				{
					CloseInstance(_detailForm);
					if (null != _detailForm && !_detailForm.IsDisposed)
						_detailForm.Dispose(true);
				}
			}
			catch (Exception ex)
			{
				try
				{
					CloseInstance(_detailForm);
				}
				catch { }
				try
				{
					if (null != _detailForm && !_detailForm.IsDisposed)
						_detailForm.Dispose(true);
				}
				catch { }
				result = DialogResult.Cancel;
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return result;
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <typeparam name="TEditor">The Editor Type to Load</typeparam>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		public static DialogResult LoadInstance<TEditor>(string FormTitle, IDataContainer Data, ModuleActions Action)
			where TEditor : DetailModuleBase
		{
			return LoadInstance<TEditor>(FormTitle, Data, Action, true, null);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <typeparam name="TEditor">The Editor Type to Load</typeparam>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owing Parent Form</param>
		public static DialogResult LoadInstance<TEditor>(string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog, IWin32Window owner)
			where TEditor : DetailModuleBase
		{
			TEditor editor = default(TEditor);
			DialogResult result = DialogResult.None;
			DetailModuleContainer editorForm = null;

			try
			{
				editorForm = new DetailModuleContainer();
				editorForm.Name = "DetailModuleContainer" + editorForm.GetHashCode().ToString("x");
				editorForm.IsActive = true;
				_instances.Add(editorForm.Name, editorForm);
				System.Threading.Interlocked.Increment(ref _instanceCount);

				editor = Activator.CreateInstance<TEditor>();

				DetailModuleContainer.InitializeModuleContainer(editorForm, editor, typeof(TEditor).Name + InstanceCount.ToString());

				if (editorForm.InitializeModule(Action, Data, ShowAsDialog, FormTitle))
				{
					if (ShowAsDialog)
					{
						result = editorForm.ShowDialog(owner);
						if (null != editorForm && !editorForm.IsDisposed)
							editorForm.Dispose(true);
					}
					else
					{
						editorForm.Show(owner);
						editorForm.BringToFront();
					}
				}
				else
				{
					CloseInstance(editorForm);
					if (null != editorForm && !editorForm.IsDisposed)
						editorForm.Dispose(true);
				}
			}
			catch (Exception ex)
			{
				CloseInstance(editorForm);
				if (null != editorForm && !editorForm.IsDisposed)
					editorForm.Dispose(true);
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return result;
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <param name="DerivedContainer">The DerivedContainer</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		public static DialogResult LoadInstance<TEditor>(DetailModuleContainer DerivedContainer, string FormTitle, IDataContainer Data, ModuleActions Action)
			where TEditor : DetailModuleBase
		{
			return LoadInstance<TEditor>(DerivedContainer, FormTitle, Data, Action, true, null);
		}
		/// <summary>
		/// Load the Container Form using the specified module
		/// </summary>
		/// <typeparam name="TEditor">The Type of Module to Load into the Container</typeparam>
		/// <param name="DerivedContainer">The DerivedContainer</param>
		/// <param name="FormTitle">The Title to display</param>
		/// <param name="Data">The Data for this form</param>
		/// <param name="Action">The Form Action to intialize the form with</param>
		/// <param name="ShowAsDialog">Indicates if the instance should be shown as a Modal Dialog</param>
		/// <param name="owner">The Owing Parent Form</param>
		public static DialogResult LoadInstance<TEditor>(DetailModuleContainer DerivedContainer, string FormTitle, IDataContainer Data, ModuleActions Action, bool ShowAsDialog, IWin32Window owner)
			where TEditor : DetailModuleBase
		{
			TEditor _childModule = default(TEditor);
			DialogResult result = DialogResult.None;
			DetailModuleContainer _detailForm = null;

			try
			{
				if (null != DerivedContainer)
				{
					_detailForm = DerivedContainer;
					_detailForm.Name += _detailForm.GetHashCode().ToString("x");
				}
				else
				{
					_detailForm = new DetailModuleContainer();
					_detailForm.Name = "DetailModuleContainer" + _detailForm.GetHashCode().ToString("x");
				}

				_detailForm.IsActive = true;
				_instances.Add(_detailForm.Name, _detailForm);
				System.Threading.Interlocked.Increment(ref _instanceCount);

				_childModule = Activator.CreateInstance<TEditor>();

				DetailModuleContainer.InitializeModuleContainer(_detailForm, _childModule, typeof(TEditor).Name + InstanceCount.ToString());

				// Initialize the Module
				if (_detailForm.InitializeModule(Action, Data, ShowAsDialog, FormTitle))
				{
					if (ShowAsDialog)
					{
						result = _detailForm.ShowDialog(owner);
						if (null != _detailForm && !_detailForm.IsDisposed)
							_detailForm.Dispose(true);
					}
					else
					{
						_detailForm.Show(owner);
						_detailForm.BringToFront();
					}
				}
				else
				{
					CloseInstance(_detailForm);
					if (null != _detailForm && !_detailForm.IsDisposed)
						_detailForm.Dispose(true);
				}
			}
			catch (Exception ex)
			{
				CloseInstance(_detailForm);
				if (null != _detailForm && !_detailForm.IsDisposed)
					_detailForm.Dispose(true);
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return result;
		}
		/// <summary>
		/// Initializes the dynamically added Module
		/// </summary>
		/// <param name="ModuleContainerInstance">The DetailModuleContainer</param>
		/// <param name="ModuleInstance">The Module to add</param>
		/// <param name="KeyName">The name to associate with the Module</param>
		public static void InitializeModuleContainer(DetailModuleContainer ModuleContainerInstance, DetailModuleBase ModuleInstance, string KeyName)
		{
			if (null != ModuleInstance)
			{
				ModuleInstance.Name = KeyName;
				ModuleInstance.Visible = true;
				ModuleInstance.Dock = DockStyle.Fill;
				ModuleInstance.DirtyChanged += new EventHandler<DirtyEventArgs>(ModuleContainerInstance._childModule_Dirty);
				ModuleInstance.AllowCreateNewChanged += new EventHandler(ModuleContainerInstance._childModule_AllowCreateNewChanged);
				ModuleInstance.AllowEditChanged += new EventHandler(ModuleContainerInstance._childModule_AllowEditChanged);
				ModuleInstance.ShowApplyButtonChanged += new EventHandler(ModuleContainerInstance._childModule_ShowApplyButtonChanged);

				ModuleContainerInstance._childModule = ModuleInstance;

				ModuleContainerInstance.StartPosition = ModuleInstance.ParentStartPosition;

				ModuleContainerInstance.ResizeParent();

				ModuleContainerInstance.pnlDetail.Controls.Add(ModuleContainerInstance._childModule);
			}
			else
				throw new ArgumentNullException("ModuleInstance", "The Module [" + KeyName + "] is not instantiated or is null");
		}
		/// <summary>
		/// Closes a DetailModuleContainer instance
		/// </summary>
		/// <param name="instance">A DetailModuleContainer instance</param>
		private static void CloseInstance(DetailModuleContainer instance)
		{
			if (null != instance)
			{
				try { }
				finally
				{
					try
					{
						string name = instance.Name;
						if (DetailModuleContainer._instances.ContainsKey(name))
						{
							DetailModuleContainer._instances.Remove(name);
							System.Threading.Interlocked.Decrement(ref _instanceCount);
						}
					}
					catch { }
				}
			}
		}
		#endregion
	}
	#endregion

	#region DetailDataSavedEventArgs
	/// <summary>
	/// DetailDataSavedEventArgs
	/// </summary>
	public class DetailDataSavedEventArgs : EventArgs
	{
		/// <summary>
		/// CTOR
		/// </summary>
		public DetailDataSavedEventArgs()
		{
		}
		/// <summary>
		/// CTOR
		/// </summary>
		/// <param name="SavedData">The Data after changes have been completed and saved</param>
		public DetailDataSavedEventArgs(IDataContainer SavedData)
		{
			_savedData = SavedData;
		}
		/// <summary>
		/// The Data after changes have been completed and saved
		/// </summary>
		public IDataContainer SavedData
		{
			get { return _savedData; }
			set { _savedData = value; }
		} IDataContainer _savedData;
	}
	#endregion
}